package controller

import (
	{{.Path}} "ics/apps/{{.Path}}/document"
	"ics/config/code"
	"ics/custom/cc"
	"gitee.com/dreamwood/ez-go/ez"
	"gitee.com/dreamwood/ez-go/ezc"
	"gitee.com/dreamwood/ez-go/ss"
	"bytes"
	"encoding/json"
	"fmt"
	"gitee.com/dreamwood/ez-go/filebus"
	"gitee.com/dreamwood/ez-go/tools"
	"github.com/xuri/excelize/v2"
	"ics/apps/{{.Path}}/auto/mc"
	"ics/libs/excel"
	"reflect"
)

type {{.Name}}AutoController struct {
	ezc.BaseAdminController
	ImportHandler map[string]func(val string) interface{}
}

func (c {{.Name}}AutoController) AccessControl(session *ez.Session) {
	//session.StopHandle()
}
func (c {{.Name}}AutoController) SaveAction(session *ez.Session) {
	this := cc.New(session)
	model := new({{.Path}}.{{.Name}})
	if this.Try(this.FillJson(model)) {
		return
	}
	if ac := {{.Path}}.New{{.Name}}AccessControl(model, "save", session); !ac.Access {
		this.ReturnError(code.ErrorAccess, ac.Message, "")
		return
	}
	model.SetEvent(true)
	model.SetFactoryParams(session)
	if this.Try(model.Save()) {
		return
	}
	this.ReturnSuccess("OK", model)
}
func (c {{.Name}}AutoController) GetAction(session *ez.Session) {
	this := cc.New(session)
	model, err := {{.Path}}.New{{.Name}}Crud(session).FindId(this.Get("id").IsInt64())
	if this.Try(err) {
		return
	}
	if ac := {{.Path}}.New{{.Name}}AccessControl(model, "get", session); !ac.Access {
		this.ReturnError(code.ErrorAccess, ac.Message, "")
		return
	}
	this.ReturnSuccess("OK", model)
}
func (c {{.Name}}AutoController) ChoiceAction(session *ez.Session) {
	this := cc.New(session)
	this.GetHttpQuery()
	list := make([]*{{.Path}}.{{.Name}}, 0)
	err := {{.Path}}.New{{.Name}}Crud(session).Factory.AggregateFind(&list, this.HttpQuery)
	if this.Try(err) {
		return
	}
	count, err := {{.Path}}.New{{.Name}}Crud(session).Factory.AggregateCount(this.HttpQuery)
	if this.Try(err) {
		return
	}
	choices := make([]*ss.M, 0)
	for _, row := range list {
		choices = append(choices, row.MakeChoice())
	}
	this.ReturnSuccess("OK", ss.M{
		"lists": choices,
		"query": ss.M{"page": this.HttpQuery.Page, "limit": this.HttpQuery.Limit, "total": count},
	})
}
func (c {{.Name}}AutoController) ListAction(session *ez.Session) {
	this := cc.New(session)
	this.GetHttpQuery()
	list := make([]*{{.Path}}.{{.Name}}, 0)
	err := {{.Path}}.New{{.Name}}Crud(session).Factory.AggregateFind(&list, this.HttpQuery)
	if this.Try(err) {
		return
	}
	count, err := {{.Path}}.New{{.Name}}Crud(session).Factory.AggregateCount(this.HttpQuery)
	if this.Try(err) {
		return
	}
	this.ReturnSuccess("ok", ss.M{
		"lists": list,
		"query": ss.M{"page": this.HttpQuery.Page, "limit": this.HttpQuery.Limit, "total": count},
	})
}
func (c {{.Name}}AutoController) DeleteAction(session *ez.Session) {
	this := cc.New(session)
	model, err := {{.Path}}.New{{.Name}}Crud(session).FindId(this.Get("id").IsInt64())
	if this.Try(err) {
		return
	}
	if ac := {{.Path}}.New{{.Name}}AccessControl(model, "delete", session); !ac.Access {
		this.ReturnError(code.ErrorAccess, ac.Message, "")
		return
	}
	model.SetEvent(true)
	if this.Try(model.Delete()) {
		return
	}
	this.ReturnSuccess("OK", model)
}
func (c {{.Name}}AutoController) UnDeleteAction(session *ez.Session) {
	this := cc.New(session)
	crud := {{.Path}}.New{{.Name}}Crud(session)
    crud.Factory.IncludeDeleted = true
    model, err := crud.FindId(this.Get("id").IsInt64())
	if this.Try(err) {
		return
	}
	model.SetEvent(true)
	if this.Try(model.UnDelete()) {
		return
	}
	this.ReturnSuccess("OK", model)
}
func (c {{.Name}}AutoController) DeleteManyAction(session *ez.Session) {
	this := cc.New(session)
	ids := ss.NewIds()
	if this.Try(this.FillJson(ids)) {
		return
	}
	list, err := {{.Path}}.New{{.Name}}Crud(session).FindBy(ss.M{
		"id__in": ids.Ids,
	}, nil, 0, 0)
	if this.Try(err) {
		return
	}
	for _, row := range list {
		row.SetEvent(true)
		if ac := {{.Path}}.New{{.Name}}AccessControl(row, "delete", session); !ac.Access {
			this.ReturnError(code.ErrorAccess, ac.Message, "")
			return
		}
		//if this.Try(row.Delete()) {
		//	return
		//}
		row.Delete()
	}
	this.ReturnSuccess("OK", "删除成功")
}
func (c {{.Name}}AutoController) DestroyAction(session *ez.Session) {
	this := cc.New(session)
	model, err := {{.Path}}.New{{.Name}}Crud(session).FindId(this.Get("id").IsInt64())
	if this.Try(err) {
		return
	}
	model.SetEvent(true)
	if this.Try(model.Destroy()) {
		return
	}
	this.ReturnSuccess("OK", model)
}
func (c {{.Name}}AutoController) DestroyManyAction(session *ez.Session) {
	this := cc.New(session)
	ids := ss.NewIds()
	if this.Try(this.FillJson(ids)) {
		return
	}
	list, err := {{.Path}}.New{{.Name}}Crud(session).FindBy(ss.M{
		"id__in": ids.Ids,
	}, nil, 0, 0)
	if this.Try(err) {
		return
	}
	for _, row := range list {
		if ac := {{.Path}}.New{{.Name}}AccessControl(row, "destroy", session); !ac.Access {
			this.ReturnError(code.ErrorAccess, ac.Message, "")
			return
		}
		row.SetEvent(true)
		if this.Try(row.Destroy()) {
			return
		}
	}
	this.ReturnSuccess("OK", "销毁成功")
}
func (c {{.Name}}AutoController) CopyAction(session *ez.Session) {
	this := cc.New(session)
	idVo := new(ss.DocIds)
	if this.Try(this.FillJson(idVo)) {
		return
	}
	for _, id := range idVo.Ids {
		model, err := {{.Path}}.New{{.Name}}Crud(session).FindId(id)
		if this.Try(err) {
			return
		}
		if ac := {{.Path}}.New{{.Name}}AccessControl(model, "copy", session); !ac.Access {
			this.ReturnError(code.ErrorAccess, ac.Message, "")
			return
		}
		model.Id = 0
		model.SetEvent(true)
		if this.Try(model.Save()) {
			return
		}
	}
	this.ReturnSuccess("OK", idVo)
}
func (c {{.Name}}AutoController) UpdateAction(session *ez.Session) {
	this := cc.New(session)
	updater := ss.NewDocUpdater()
	if this.Try(this.FillJson(updater)) {
		return
	}
	//id, _ := primitive.ObjectIDFromHex(updater.Id)
	doc := &{{.Path}}.{{.Name}}{Id: updater.Id}
	if ac := {{.Path}}.New{{.Name}}AccessControl(doc, "update", session); !ac.Access {
		this.ReturnError(code.ErrorAccess, ac.Message, "")
		return
	}
	if this.Try({{.Path}}.New{{.Name}}Crud(session).Factory.Update(doc, updater.Model)) {
		return
	}
	this.ReturnSuccess("OK", updater)
}
func (c {{.Name}}AutoController) UpdateManyAction(session *ez.Session) {
	this := cc.New(session)
	updater := ss.NewDocUpdater()
	if this.Try(this.FillJson(updater)) {
		return
	}
	for _, id := range updater.Ids {
		doc := &{{.Path}}.{{.Name}}{Id: id}
		if ac := {{.Path}}.New{{.Name}}AccessControl(doc, "update", session); !ac.Access {
			this.ReturnError(code.ErrorAccess, ac.Message, "")
			return
		}
		if this.Try({{.Path}}.New{{.Name}}Crud(session).Factory.Update(doc, updater.Model)) {
			return
		}
	}
	this.ReturnSuccess("OK", updater)
}

func (c {{.Name}}AutoController) ImportAction(session *ez.Session) {
	this := cc.New(session)
	fileUrl := this.Get("url").IsString()
	content := tools.DownLoadFile(fileUrl)
	file, e := excelize.OpenReader(bytes.NewReader(content))
	if this.Try(e) {
		return
	}
	impt := excel.NewImporter()
	impt.File = file
	ref := reflect.ValueOf({{.Path}}.{{.Name}}{})
	//读取第一行标题
	keys := make([]string, 0)
	headerCol := 1
	for true {
		text := impt.GetTextByIndex(1, headerCol)
		if text == "" {
			break
		}
		keys = append(keys, text)
		headerCol++
	}
	start := 3
	crud := {{.Path}}.New{{.Name}}Crud(session)
	for {
		empty := ""
		row := ss.M{}
		for index, key := range keys {
			field := ref.FieldByName(tools.Ucfirst(key))
			switch field.Type().String() {
			case "string":
				value := impt.GetTextByIndex(start, index+1)
				row[key] = value
			case "float64":
				value := impt.GetFloatByIndex(start, index+1)
				row[key] = value
			case "int64":
				value := impt.GetIntByIndex(start, index+1)
				row[key] = value
			case "bool":
				value := impt.GetIntByIndex(start, index+1)
				row[key] = value != 0
			case "time.Time":
				value := impt.GetTimeByIndex(start, index+1)
				if value != nil {
					row[key] = *value
				}
			case "*time.Time":
				value := impt.GetTimeByIndex(start, index+1)
				row[key] = value
			default:
				//row[key] = field.Type().String()
			}
			if c.ImportHandler != nil {
				if f, ok := c.ImportHandler[key]; ok {
					value := impt.GetTextByIndex(start, index+1)
					row[key] = f(value)
				}
			}
			empty += impt.GetTextByIndex(start, index+1)
		}
		if len(empty) > 0 {
			jsonData, _ := json.Marshal(row)
			model := {{.Path}}.{{.Name}}{}
			model.UnSerialize(jsonData)
			if model.Id > 0 {
				find, _ := crud.FindId(model.Id)
				if find.Id > 0 {
					err := model.GetFactory().Update(find, row)
					if err != nil {
						println(err)
					}
				} else {
					err := model.GetFactory().Create(&model)
					if err != nil {
						println(err)
					}
				}
			} else {
				_ = model.Save()
			}
			start++
		} else {
			break
		}

	}
	this.ReturnSuccess("OK", "导入成功")

}
func (c {{.Name}}AutoController) ExportAction(session *ez.Session) {
	this := cc.New(session)
	templateName := this.Get("t").IsString("default")
	list := make([]*{{.Path}}.{{.Name}}, 0)
	this.GetHttpQuery()
	err := {{.Path}}.New{{.Name}}Crud(session).Factory.AggregateFind(&list, this.HttpQuery)
	if this.Try(err) {
		return
	}
	expt := excel.NewExcelExporter()
	//创建头部
	excelConfig, ok := mc.Get{{.Name}}Config().ExcelFields[templateName]
	if !ok {
		this.ReturnError(code.Error, "导出受限", "")
		return
	}
	for i, key := range excelConfig.Values {
		_ = expt.WriteTo(i+1, 1, key)
		_ = expt.WriteTo(i+1, 2, excelConfig.Names[i])
	}
	for i, product := range list {
		writeSrc := ss.M{}
		_ = json.Unmarshal(product.ToBytes(), &writeSrc)
		for col, key := range excelConfig.Values {
			_ = expt.WriteTo(col+1, i+3, writeSrc[key])
		}
	}
	targetFile := filebus.CreateRandFile(".xlsx")
	_ = tools.CreateDirForPath(targetFile)
	_ = expt.CreateFile(targetFile)
	fb := filebus.NewFileBus()
	fb.Url = fmt.Sprintf("%s%s", ez.GetServerHttpUrl(), targetFile[1:])
	fb.Name = fmt.Sprintf("{{.CnName}}导出%s", tools.GetDateYMDHIS("", "", ""))
	fb.Uid = this.GetUserId()
	fb.Send()
	this.ReturnSuccess("导出成功", "")
}


{{if eq .IsTree true}}
func (c {{$.Name}}AutoController) TreeAction(session *ez.Session) {
	this := cc.New(session)
	this.GetHttpQuery()
	if len(this.HttpQuery.Conditions) == 0 {
    		this.HttpQuery.Conditions["parentId"] = 0
    	}
	list := make([]*{{.Path}}.{{$.Name}}, 0)
	err := {{.Path}}.New{{$.Name}}Crud(session).Factory.AggregateFind(&list, this.HttpQuery)
	if this.Try(err) {
		return
	}
	data := make([]*ss.M, len(list))
	for i, md := range list {
		md.LoadChildren()
		data[i] = md.MakeTree()
	}
	this.ReturnSuccess("OK", data)
}
{{end}}